// Copyright 2022 PingCAP, Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <Columns/ColumnConst.h>
#include <Columns/ColumnString.h>
#include <Common/Exception.h>
#include <DataTypes/DataTypeNothing.h>
#include <Functions/FunctionFactory.h>
#include <Interpreters/Context.h>
#include <TestUtils/FunctionTestUtils.h>
#include <TestUtils/TiFlashTestBasic.h>

#include <string>
#include <unordered_map>
#include <vector>


namespace DB
{
namespace tests
{
// bitnot = tidb's bitneg.
class TestFunctionBitNot : public DB::tests::FunctionTest
{
};

#define ASSERT_BITNOT(t1, result) \
    ASSERT_COLUMN_EQ(result, executeFunction("bitNot", {t1}))

TEST_F(TestFunctionBitNot, Simple)
try
{
    ASSERT_BITNOT(createColumn<Nullable<Int64>>({-1, 1}), createColumn<Nullable<Int64>>({0, -2}));
}
CATCH

/// Note: Only IntX and UIntX will be received by BitNot, others will be casted by TiDB Planner.
TEST_F(TestFunctionBitNot, TypeTest)
try
{
    ASSERT_BITNOT(createColumn<Nullable<Int8>>({1}), createColumn<Nullable<Int8>>({-2}));
    ASSERT_BITNOT(createColumn<Nullable<Int16>>({1}), createColumn<Nullable<Int16>>({-2}));
    ASSERT_BITNOT(createColumn<Nullable<Int32>>({1}), createColumn<Nullable<Int32>>({-2}));
    ASSERT_BITNOT(createColumn<Nullable<Int64>>({1}), createColumn<Nullable<Int64>>({-2}));

    ASSERT_BITNOT(createColumn<Nullable<UInt8>>({1}), createColumn<Nullable<UInt8>>({UINT8_MAX - 1}));
    ASSERT_BITNOT(createColumn<Nullable<UInt16>>({1}), createColumn<Nullable<UInt16>>({UINT16_MAX - 1}));
    ASSERT_BITNOT(createColumn<Nullable<UInt32>>({1}), createColumn<Nullable<UInt32>>({UINT32_MAX - 1}));
    ASSERT_BITNOT(createColumn<Nullable<UInt64>>({1}), createColumn<Nullable<UInt64>>({UINT64_MAX - 1}));

    ASSERT_BITNOT(createColumn<Int8>({0, 0, 1, 1}), createColumn<Int8>({-1, -1, -2, -2}));
    ASSERT_BITNOT(createColumn<Nullable<Int8>>({0, 1, std::nullopt, std::nullopt}), createColumn<Nullable<Int8>>({-1, -2, std::nullopt, std::nullopt}));
    ASSERT_BITNOT(createConstColumn<Int8>(4, 0), createConstColumn<Int8>(4, -1));
    ASSERT_BITNOT(createConstColumn<Nullable<Int8>>(4, 0), createConstColumn<Nullable<Int8>>(4, -1));
    ASSERT_BITNOT(createConstColumn<Nullable<Int8>>(4, std::nullopt), createConstColumn<Nullable<Int8>>(4, std::nullopt));
}
CATCH

TEST_F(TestFunctionBitNot, Boundary)
try
{
    ASSERT_BITNOT(createColumn<Int64>({0, 1, -1, INT64_MAX, INT64_MIN}),
                  createColumn<Int64>({-1, -2, 0, INT64_MIN, INT64_MAX}));

    ASSERT_BITNOT(createColumn<UInt64>({0, 1, UINT64_MAX}),
                  createColumn<UInt64>({UINT64_MAX, UINT64_MAX - 1, 0}));
}
CATCH

TEST_F(TestFunctionBitNot, UINT64)
try
{
    ASSERT_BITNOT(createColumn<UInt64>({0, 0, UINT64_MAX, UINT64_MAX}),
                  createColumn<UInt64>({UINT64_MAX, UINT64_MAX, 0, 0}));

    ASSERT_BITNOT(createColumn<Nullable<UInt64>>({0, 0, UINT64_MAX, UINT64_MAX, std::nullopt}),
                  createColumn<Nullable<UInt64>>({UINT64_MAX, UINT64_MAX, 0, 0, std::nullopt}));


    /*
    std::mt19937 gen(std::random_device{}());
    std::uniform_int_distribution<unsigned long long> dis(
            std::numeric_limits<std::uint64_t>::min(),
            std::numeric_limits<std::uint64_t>::max()
    );
    size_t count = 100;
    std::vector<UINT64> v1(count), res(count);
    for (size_t i=0; i<count; ++i) {
        v1[i] = dis(gen);
        res[i] = ~v1[i];
    }
    */
    // clang-format off
    ASSERT_BITNOT(createColumn<UInt64>({2379817219568548155ull,11283008755207226540ull,9291731551180886999ull,7013369115775651514ull,9101556557732423541ull,12907500993652003920ull,9895224623502948020ull,17037371654928340115ull,16231913252254922661ull,13055498361500506774ull,10988310020057726111ull,12586443140813353273ull,468212273018917010ull,6005277627692613752ull,5956075053283467910ull,14200314399154907528ull,2893438148803776092ull,3085591881768571311ull,614745240593304977ull,17902554835649013005ull,761970710384668108ull,12256066165076077511ull,4350979650561986522ull,7427512137792140325ull,6160214653562546765ull,9669918478864767970ull,17095794173782657005ull,7506815911976714360ull,12879144241595183456ull,15888983833254769243ull,15461590394326619703ull,6156541322006848188ull,12425045703423641103ull,7037015244147180323ull,11002413584478683962ull,16688451762591474648ull,15328212506777870113ull,389787597643261259ull,17261433059614971760ull,3477285793362927980ull,1742149683116055811ull,15006291102057836296ull,12215453980330943673ull,18025691082037647523ull,14312625164543748936ull,7376672191024366721ull,2184638021506425098ull,14406847488843383475ull,6581385976025122158ull,15850683291288702637ull,10663442551897081961ull,3200414484972707217ull,17074933269953368467ull,7590260732674305927ull,10215263846810271307ull,7258741368070765774ull,635382332695914514ull,1446893380128012235ull,4410808088098778140ull,2527822586824136318ull,6720529508870502081ull,17794609820039171456ull,16994979889444399198ull,12281325983994080517ull,18083751608860397030ull,13335977696250360933ull,8113832842343857697ull,3962855843068092803ull,3376082225245390224ull,4410100346871656490ull,8610329736560707860ull,17060558976524306989ull,9966988877331319869ull,33163630734960355ull,1715226598764388916ull,4506310409141886239ull,15765388092312416395ull,13945626685289576573ull,2877825509043800689ull,7194939891583245799ull,5423238611760218264ull,16427029295817927010ull,18199965596862741012ull,9393052996108109509ull,8885160812439244734ull,11743742735416946321ull,6910437827800037444ull,209330585366237851ull,17509536944135980940ull,6425864657796143019ull,16584894514728454035ull,10901337350786765099ull,11027497054315035524ull,11196314726831539525ull,13393106335872968738ull,14800898192970221111ull,7449199014979252266ull,8097815721687449709ull,14763654429616547036ull,16697042582703752480ull,
                                       }),
                  createColumn<UInt64>({16066926854141003460ull,7163735318502325075ull,9155012522528664616ull,11433374957933900101ull,9345187515977128074ull,5539243080057547695ull,8551519450206603595ull,1409372418781211500ull,2214830821454628954ull,5391245712209044841ull,7458434053651825504ull,5860300932896198342ull,17978531800690634605ull,12441466446016937863ull,12490669020426083705ull,4246429674554644087ull,15553305924905775523ull,15361152191940980304ull,17831998833116246638ull,544189238060538610ull,17684773363324883507ull,6190677908633474104ull,14095764423147565093ull,11019231935917411290ull,12286529420147004850ull,8776825594844783645ull,1350949899926894610ull,10939928161732837255ull,5567599832114368159ull,2557760240454782372ull,2985153679382931912ull,12290202751702703427ull,6021698370285910512ull,11409728829562371292ull,7444330489230867653ull,1758292311118076967ull,3118531566931681502ull,18056956476066290356ull,1185311014094579855ull,14969458280346623635ull,16704594390593495804ull,3440452971651715319ull,6231290093378607942ull,421052991671904092ull,4134118909165802679ull,11070071882685184894ull,16262106052203126517ull,4039896584866168140ull,11865358097684429457ull,2596060782420848978ull,7783301521812469654ull,15246329588736844398ull,1371810803756183148ull,10856483341035245688ull,8231480226899280308ull,11188002705638785841ull,17811361741013637101ull,16999850693581539380ull,14035935985610773475ull,15918921486885415297ull,11726214564839049534ull,652134253670380159ull,1451764184265152417ull,6165418089715471098ull,362992464849154585ull,5110766377459190682ull,10332911231365693918ull,14483888230641458812ull,15070661848464161391ull,14036643726837895125ull,9836414337148843755ull,1386185097185244626ull,8479755196378231746ull,18413580442974591260ull,16731517474945162699ull,13940433664567665376ull,2681355981397135220ull,4501117388419975042ull,15568918564665750926ull,11251804182126305816ull,13023505461949333351ull,2019714777891624605ull,246778476846810603ull,9053691077601442106ull,9561583261270306881ull,6703001338292605294ull,11536306245909514171ull,18237413488343313764ull,937207129573570675ull,12020879415913408596ull,1861849558981097580ull,7545406722922786516ull,7419247019394516091ull,7250429346878012090ull,5053637737836582877ull,3645845880739330504ull,10997545058730299349ull,10348928352022101906ull,3683089644093004579ull,1749701491005799135ull,
                                       }));
    // clang-format on
}
CATCH

} // namespace tests
} // namespace DB
